﻿#region Copyright

// The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (the "License"); you may not use this file except in compliance
//  with the License. You may obtain a copy of the License at
//  
//  http://www.mozilla.org/MPL/
//  
//  Software distributed under the License is distributed on an "AS IS"
//  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
//  License for the specific language governing rights and limitations under 
//  the License.
//  
//  The Initial Developer of the Original Code is Robert Smyth.
//  Portions created by Robert Smyth are Copyright (C) 2008.
//  
//  All Rights Reserved.

#endregion

using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Media;
using NUnitGrid.Framework;
using NUnitGrid.Framework.Plugins;
using NUnitGrid.Framework.UI;


namespace NUnitGrid.Server.Plugins.Nodes.UI.NodesList
{
    public class NodesListElementPlugin : IGridNodesListener, IUIChildPlugin, IScheduledEventListener
    {
        private readonly Dictionary<IGridNode, IListRow> displayedNodes = new Dictionary<IGridNode, IListRow>();
        private readonly IListView listView;
        private readonly ISchedule schedule;
        private IListColumn failedTasksCountColumn;
        private IListColumn machineNameColumn;
        private IListColumn nickNameColumn;
        private IListColumn processorsColumn;
        private IListColumn statusColumn;
        private IListColumn taskRunTimeColumn;
        private IListColumn tasksCountColumn;
        private IListColumn versionColumn;

        public NodesListElementPlugin(IListView listView, ISchedule schedule)
        {
            this.listView = listView;
            this.schedule = schedule;
        }

        void IGridNodesListener.OnNodesChanged(IGridNode[] nodes)
        {
            var missingNodes = new List<IGridNode>(displayedNodes.Keys);

            foreach (var node in nodes)
            {
                if (missingNodes.Contains(node))
                {
                    missingNodes.Remove(node);
                }

                if (displayedNodes.ContainsKey(node))
                {
                    var row = displayedNodes[node];
                    SetRowValues(node, row);
                }
                else
                {
                    AddNodeToDisplay(node);
                }
            }

            foreach (var node in missingNodes)
            {
                var row = displayedNodes[node];
                displayedNodes.Remove(node);
                listView.Remove(row);
            }
        }

        void IScheduledEventListener.OnEventFired()
        {
            foreach (var pair in displayedNodes)
            {
                UpdateRunTime(pair.Value, pair.Key);
            }

            schedule.AddEvent(this, TimeSpan.FromSeconds(1));
        }

        void IUIChildPlugin.Start(IHostView hostView)
        {
            listView.Label = "Nodes";
            listView.Foreground = new SolidColorBrush(Colors.WhiteSmoke);

            machineNameColumn = listView.AddColumn("Machine name");
            nickNameColumn = listView.AddColumn("Nickname");
            statusColumn = listView.AddColumn("Status");
            processorsColumn = listView.AddColumn("Processors");
            tasksCountColumn = listView.AddColumn("Tasks");
            failedTasksCountColumn = listView.AddColumn("Failures");
            taskRunTimeColumn = listView.AddColumn("Time running");
            versionColumn = listView.AddColumn("Version");

            hostView.AddChild(listView);

            schedule.AddEvent(this, TimeSpan.FromSeconds(2));
        }

        void IUIChildPlugin.Stop(IHostView view)
        {
        }

        private void SetRowValues(IGridNode node, IListRow row)
        {
            row.SetField(machineNameColumn, node.MachineName);
            row.SetField(nickNameColumn, node.Nickname);
            row.SetField(statusColumn, node.Busy ? "Busy" : "Available");
            row.SetField(processorsColumn,
                         string.Format("{0} x {1}GHz", node.NumberOfProcessors, node.ProcessorMHz/1000.0D));
            row.SetField(tasksCountColumn, node.TasksCount.ToString());
            row.SetField(failedTasksCountColumn, node.FailedTasksCount.ToString());
            row.SetField(versionColumn, node.SoftwareVersion);
            UpdateRunTime(row, node);
        }

        private void AddNodeToDisplay(IGridNode node)
        {
            var row = listView.Add(node.MachineName, "Available");
            SetRowValues(node, row);
            displayedNodes.Add(node, row);
        }

        private void UpdateRunTime(IListRow row, IGridNode node)
        {
            var expiredTime = node.CurrentTaskRunTime;
            row.SetField(taskRunTimeColumn,
                         node.TasksCount == 0
                             ? string.Empty
                             : string.Format("{0:00}:{1:00}", (int) expiredTime.TotalMinutes, expiredTime.Seconds));
        }
    }
}